import json
import logging

from decimal import Decimal

from django.http import JsonResponse
from django.views import View
from django_redis import get_redis_connection
from django.utils import timezone
from django.db import transaction

from apps.orders.models import OrderInfo, OrderGoods
from apps.users.models import Address
from apps.goods.models import SKU
from utils.views import LoginRequiredJSONMixin


class OrderSettlementView(LoginRequiredJSONMixin, View):

    def get(self, request):
        user = request.user
        # 查询当前用户的所有地址信息
        addresses = Address.objects.filter(user=request.user,
                                           is_deleted=False)
        # 连接redis
        redis_cli = get_redis_connection('carts')
        redis_cart = redis_cli.hgetall('carts_%s' % user.id)
        cart_selected = redis_cli.smembers('selected_%s' % user.id)
        cart_dict = {}
        for sku_id in cart_selected:
            cart_dict[int(sku_id)] = int(redis_cart[sku_id])

        cart_list = []
        skus = SKU.objects.filter(id__in=cart_dict.keys())
        for sku in skus:
            cart_list.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'count': cart_dict[sku.id],
                'price': sku.price
            })

        # 补充运费
        freight = Decimal('10.00')

        address_list = []
        for address in addresses:
            address_list.append({
                'id': address.id,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'place': address.place,
                'receiver': address.receiver,
                'mobile': address.mobile
            })
        context = {
            'addresses': address_list,
            'skus': cart_list,
            'freight': freight,
        }

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'context': context})


class OrderCommitView(LoginRequiredJSONMixin, View):

    def post(self, request):
        user = request.user
        data = json.loads(request.body)
        address_id = data.get('address_id')
        pay_method = data.get('pay_method')
        # 校验参数
        if not all([address_id, pay_method]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        # 判断address_id是否合法
        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '参数不正确'})
            # 判断pay_method是否合法
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return JsonResponse({'code': 400, 'errmsg': '参数不正确'})

        # 显性地开启一个事务
        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()
            try:
                # 生成订单号
                order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal('0'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
                        'ALIPAY'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )

                # 读取购物车商品信息
                redis_cli = get_redis_connection('carts')
                redis_cart = redis_cli.hgetall('carts_%s' % user.id)
                selected_cart = redis_cli.smembers('selected_%s' % user.id)
                cart_dict = {}
                for sku_id in selected_cart:
                    cart_dict[int(sku_id)] = int(redis_cart[sku_id])

                sku_ids = cart_dict.keys()
                for sku_id in sku_ids:
                    sku = SKU.objects.get(id=sku_id)
                    # 读取原始库存
                    origin_stock = sku.stock
                    origin_sales = sku.sales
                    # 判断库存是否足够
                    sku_count = cart_dict[sku_id]
                    if sku_count > sku.stock:
                        transaction.savepoint_rollback(save_id)
                        return JsonResponse({'code': 400, 'errmsg': '库存不足'})
                    # 更新销售量和库存量
                    # sku.stock -= sku_count
                    # sku.sales += sku_count
                    # sku.save()
                    new_stock = origin_stock - sku_count
                    new_sales = origin_sales + sku_count
                    result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock)
                    if result == 0:
                        continue
                    OrderGoods.objects.create(
                        order=order,
                        sku=sku,
                        count=sku_count,
                        price=sku.price
                    )
                    order.total_count += sku_count
                    order.total_amount += (sku_count * sku.price)

                order.total_amount += order.freight
                order.save()
            except Exception as e:
                logging.error(e)
                # 如果失败，回滚到保存点
                transaction.savepoint_rollback(save_id)
                return JsonResponse({'code': 400, 'errmsg': '下单失败'})
            # 成功下单，提交该事务
            transaction.savepoint_commit(save_id)

        pl = redis_cli.pipeline()
        pl.hdel('carts_%s' % user.id, *selected_cart)
        pl.srem('selected_%s' % user.id, *selected_cart)
        pl.execute()

        # 响应提交订单结果
        return JsonResponse({'code': 0, 'errmsg': '下单成功', 'order_id': order.order_id})
